/****************************************************************************
 * Copyright (C) 2025 Chenyz. All rights reserved.
 *
 * @file    TinyOS_List.c
 *
 * @par     dependencies
 *
 * @author  Chenyz
 *
 * @brief   Linked list implementation module for TinyOS with following features:
 *          - Doubly-linked list implementation
 *          - Head node acting as sentinel for boundary conditions
 *          - Support for node insertion, deletion and traversal
 *          - Configurable node counting
 *          - Memory-efficient design with minimal overhead
 *          - Cross-platform compatibility (bare-metal/RTOS systems)
 *
 * @version V1.0
 * @date    2025-09-15
 *
 * @note    Coding standard:
 *          - 4 spaces per indent level
 *          - Follow MISRA-C 2012 guidelines
 *          - Compiler compatibility: C99 and above
 *
 ****************************************************************************/

/******************************** Includes **********************************/
#include "TinyOS_Lib.h"

/******************************** Defines ***********************************/
#define LIST_FISRT_NODE     HeadNode.NextNode
#define LIST_LAST_NODE      HeadNode.PreNode


/**
 * @brief Initializes a node for use in a linked list
 * 
 * This function prepares a node by setting its next and previous pointers
 * to point to itself, indicating it's not part of any list.
 * 
 * @param Node Pointer to the node to be initialized
 */
void TinyOS_NodeInit(TinyOS_NodeType* Node)
{
    if(Node == NULL)
    {
        return;
    }
    Node->NextNode = Node;
    Node->PreNode = Node;
}

/**
 * @brief Initializes a linked list structure
 * 
 * Sets up an empty list with the head node pointing to itself
 * and node count set to zero.
 * 
 * @param List Pointer to the list structure to be initialized
 */
void TinyOS_ListInit(TinyOS_ListType* List)
{
    if(List == NULL)
    {
        return;
    }
    List->LIST_FISRT_NODE = &(List->HeadNode);
    List->LIST_LAST_NODE = &(List->HeadNode);
    List->NodeCount = 0;
}

/**
 * @brief Returns the number of nodes in the list
 * 
 * @param List Pointer to the list structure
 * @return uint32_t Number of nodes in the list, 0 if list is NULL
 */
uint32_t TinyOS_ListNodeCount(TinyOS_ListType* List)
{
    if(List == NULL)
    {
        return 0;
    }
    return List->NodeCount;
}

/**
 * @brief Returns the first node in the list
 * 
 * @param List Pointer to the list structure
 * @return TinyOS_NodeType* Pointer to the first node, NULL if list is empty or invalid
 */
TinyOS_NodeType* TinyOS_ListFirstNode(TinyOS_ListType* List)
{
    if(List == NULL)
    {
        return (TinyOS_NodeType*)0;
    }
    if(List->NodeCount)
    {
        return List->LIST_FISRT_NODE;
    }else
    {
        return (TinyOS_NodeType*)0;
    }
}

/**
 * @brief Returns the last node in the list
 * 
 * @param List Pointer to the list structure
 * @return TinyOS_NodeType* Pointer to the last node, NULL if list is empty or invalid
 */
TinyOS_NodeType* TinyOS_ListLastNode(TinyOS_ListType* List)
{
    if(List == NULL)
    {
        return (TinyOS_NodeType*)0;
    }
    if(List->NodeCount)
    {
        return List->LIST_LAST_NODE;
    }else
    {
        return (TinyOS_NodeType*)0;
    }
}

/**
 * @brief Finds the previous node of a given node in the list
 * 
 * @param List Pointer to the list structure
 * @param Node Pointer to the node whose previous node is to be found
 * @return TinyOS_NodeType* Pointer to the previous node, NULL if not found or invalid parameters
 */
TinyOS_NodeType* TinyOS_ListFindPreNode(TinyOS_ListType* List, TinyOS_NodeType* Node)
{
    if(List == NULL || Node == NULL)
    {
        return (TinyOS_NodeType*)0;
    }
    if(Node->PreNode == Node)
    {
        return (TinyOS_NodeType*)0;
    }
    return Node->PreNode;
}

/**
 * @brief Finds the next node of a given node in the list
 * 
 * @param List Pointer to the list structure
 * @param Node Pointer to the node whose next node is to be found
 * @return TinyOS_NodeType* Pointer to the next node, NULL if not found or invalid parameters
 */
TinyOS_NodeType* TinyOS_ListFindNextNode(TinyOS_ListType* List, TinyOS_NodeType* Node)
{
    if(List == NULL || Node == NULL)
    {
        return (TinyOS_NodeType*)0;
    }
    if(Node->NextNode == Node)
    {
        return (TinyOS_NodeType*)0;
    }
    return Node->NextNode;
}

/**
 * @brief Removes all nodes from the list and resets it to empty state
 * 
 * This function iterates through all nodes, resets their pointers to point to themselves,
 * and sets the list count to zero.
 * 
 * @param List Pointer to the list structure
 */
void TinyOS_ListRemoveAllNode(TinyOS_ListType* List)
{
    if((List == NULL) || (List->NodeCount == 0))
    {
        return;
    }   

    TinyOS_NodeType* NextNode = List->LIST_FISRT_NODE;
    
    for(uint32_t NodeCount = List->NodeCount; NodeCount!= 0; NodeCount--)
    {
        TinyOS_NodeType* CurrentNode = NextNode;
        NextNode = NextNode->NextNode;
        CurrentNode->NextNode = CurrentNode;
        CurrentNode->PreNode = CurrentNode;       
    }
    List->LIST_FISRT_NODE = &(List->HeadNode);
    List->LIST_LAST_NODE = &(List->HeadNode);
    List->NodeCount = 0;
}

/**
 * @brief Inserts a node at the beginning of the list
 * 
 * @param List Pointer to the list structure
 * @param Node Pointer to the node to be inserted
 */
void TinyOS_ListHeadInsert(TinyOS_ListType* List, TinyOS_NodeType* Node)
{
    if(List == NULL || Node == NULL)
    {
        return;
    }
    
    Node->PreNode = List->LIST_FISRT_NODE->PreNode;
    Node->NextNode = List->LIST_FISRT_NODE;
    List->LIST_FISRT_NODE->PreNode = Node;
    List->LIST_FISRT_NODE = Node;
    
    List->NodeCount++;
}

/**
 * @brief Inserts a node at the end of the list
 * 
 * @param List Pointer to the list structure
 * @param Node Pointer to the node to be inserted
 */
void TinyOS_ListTailInsert(TinyOS_ListType* List, TinyOS_NodeType* Node)
{
    if(List == NULL || Node == NULL)
    {
        return;
    }
    
    Node->PreNode = List->LIST_LAST_NODE;
    Node->NextNode = List->LIST_LAST_NODE->NextNode;
    List->LIST_LAST_NODE->NextNode = Node;
    List->LIST_LAST_NODE = Node;
    
    List->NodeCount++;
}

/**
 * @brief Deletes the first node from the list
 * 
 * @param List Pointer to the list structure
 */
TinyOS_NodeType* TinyOS_ListHeadDelete(TinyOS_ListType* List)
{
    TinyOS_NodeType* TempNode = List->LIST_FISRT_NODE;
    if(List == NULL)
    {
        return (TinyOS_NodeType*)0;
    }
    if(List->NodeCount == 0)
    {
        return(TinyOS_NodeType*)0;
    }
    if(List->NodeCount != 0)
    {
        TempNode->NextNode->PreNode = &(List->HeadNode);
        List->LIST_FISRT_NODE = TempNode->NextNode;   
        List->NodeCount--;
    }
    return TempNode;
}

/**
 * @brief Inserts a node after a specified node in the list
 * 
 * @param List Pointer to the list structure
 * @param InsertNode Pointer to the node to be inserted
 * @param AfterNode Pointer to the node after which the new node will be inserted
 */
void TinyOS_ListInsertAfterNode(
    TinyOS_ListType* List, 
    TinyOS_NodeType* InsertNode, 
    TinyOS_NodeType* AfterNode
)
{
    if(List == NULL || InsertNode == NULL || AfterNode == NULL)
    {
        return;
    }
    
    InsertNode->PreNode = AfterNode;
    InsertNode->NextNode = AfterNode->NextNode;

    AfterNode->NextNode->PreNode = InsertNode;
    AfterNode->NextNode = InsertNode;
    
    List->NodeCount++;
}
    
/**
 * @brief Deletes a specified node from the list
 * 
 * @param List Pointer to the list structure
 * @param DelteNode Pointer to the node to be deleted
 */
void TinyOS_ListDeleteNode(TinyOS_ListType* List, TinyOS_NodeType* DelteNode)
{
    if(List == NULL || DelteNode == NULL)
    {
        return;
    }    
    if(List->NodeCount ==0)
    {
        return;
    }
    DelteNode->PreNode->NextNode = DelteNode->NextNode;
    DelteNode->NextNode->PreNode = DelteNode->PreNode;
    
    List->NodeCount--;
}

